


// Relief mapping

// setup ray pos and dir based on view vector
// and apply depth bias and depth factor
void setup_ray(VertexShaderOutput IN,out float3 p,out float3 v)
{
	p = float3(IN.TexCoord,0);
	v = normalize(IN.ViewDir);
	
	v.z = abs(v.z);

	if (g_DepthBias)
	{
		float db=1.0-v.z; 
		db*=db; 
		db*=db; 
		db=1.0-db*db;
		v.xy*=db;
	}
	
	v.xy *= g_DepthScale;
}

// ray intersect depth map using linear and binary searches
// depth value stored in alpha channel (black at is object surface)
void ray_intersect_relief(
	sampler2D relief_map,
	inout float3 p,
	inout float3 v)
{
	const int num_steps_lin=15;
	const int num_steps_bin=6;
	
	v /= v.z*num_steps_lin;
	
	int i;
	for( i=0;i<num_steps_lin;i++ )
	{
		float4 tex = tex2D(relief_map, p.xy);
		if (p.z<tex.w)
			p+=v;
	}
	
	for( i=0;i<num_steps_bin;i++ )
	{
		v *= 0.5;
		float4 tex = tex2D(relief_map, p.xy);
		if (p.z<tex.w)
			p+=v;
		else
			p-=v;
	}
}


// ray intersect depth map using relaxed cone stepping
// depth value stored in alpha channel (black is at object surface)
// and cone ratio stored in blue channel
void ray_intersect_relaxedcone(
	sampler2D relaxedcone_relief_map,
	inout float3 p,
	inout float3 v)
{
	const int cone_steps=15;
	const int binary_steps=8;
	
	float3 p0 = p;

	v /= v.z;
	
	float dist = length(v.xy);
	
	for( int i=0;i<cone_steps;i++ )
	{
		float4 tex = tex2D(relaxedcone_relief_map, p.xy);

		float height = saturate(tex.w - p.z);
		
		float cone_ratio = tex.z;
		
		p += v * (cone_ratio * height / (dist + cone_ratio));
	}

	v *= p.z*0.5;
	p = p0 + v;

	for( int i=0;i<binary_steps;i++ )
	{
		float4 tex = tex2D(relaxedcone_relief_map, p.xy);
		v *= 0.5;
		if (p.z<tex.w)
			p+=v;
		else
			p-=v;
	}
}



float2 ComputeMoments(float Depth)
{
	float2 Moments;
	Moments.x = Depth;
//	float dx = ddx(Depth);
//	float dy = ddy(Depth);
	Moments.y = Depth * Depth;// + 0.25f * (dx*dx + dy*dy);
	return Moments;
}
